import random
import base64
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization, hashes


_KEY = b'''-----BEGIN ENCRYPTED PRIVATE KEY-----
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
-----END ENCRYPTED PRIVATE KEY-----
'''
_PKEY = serialization.load_pem_private_key(
    _KEY,
    password=b'dodeca256_password@DDDDDAB',
)


def _gen(serial_number: str, seed: int, timestamp: str):
    rnd = random.Random(seed)

    count = rnd.randint(7, 33)
    pos = rnd.randint(0, count - 1)
    epos = rnd.randint(0, 1_000_000)
    epos = epos - (epos % count) + pos

    data = [
        str(rnd.randint(0, 1_000_000))
        for _ in range(count)
    ]
    data[pos] = str(seed)
    data.append(str(epos))
    data.append(serial_number)
    data.append(timestamp)

    return '\n'.join(data).encode('utf-8')


def validate(serial_number: str, prev_timestamp: int, key: str) -> (bool, float):
    try:
        key = base64.b64decode(key.encode('ascii'))
        key = _PKEY.decrypt(
            key,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        data = key.decode('utf-8').split('\n')
        *data, epos, sn, timestamp = data
        if float(timestamp) < (prev_timestamp - 2):
            return False, prev_timestamp

        count = len(data)
        pos = int(epos) % count
        seed = int(data[pos])
        return key == _gen(serial_number, seed, timestamp), float(timestamp)
    except Exception:
        return False, prev_timestamp
